/*
 * 
 com.hengtiansoft.minusnight.net.JsonListRequest
 @author 徐文秀 Kate <br/>
 TODO
 create at:Aug 31, 2015.10:51:07 AM
 */
package com.hengtiansoft.lfy.chart.net;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.hengtiansoft.lfy.constants.Constants;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: JsonListRequest
 * @Description: volley请求
 * @author caijiajun
 * @date 2015年10月26日 下午2:12:57
 * 
 */
public class JsonListRequest<T> extends JsonRequest<T> {
    public final static String TAG = JsonListRequest.class.getSimpleName();
    public final static int SOCKET_TIMEOUT = 5000;
    private Gson gson;
    private Class<T> clazz;
    private String mKey;
    private Type type;
    private Type type2; // 登录成功时的数据类型
    private Boolean isLogin;
    private String cookie;
    private String requestBody;
    private SharedPreferences sharedPreferences;
    private Context context = null;

    /**
     * GET请求方式,直接将json字符串解析为 对应的clazz对象
     * 
     * @param url
     *            请求url
     * @param clazz
     *            解析的class字节码
     * @param type
     *            目标类型
     * @param isLogin
     *            是否是登录请求，若为登录请求，则在返回的响应的header中得到cookie(参见parseNetworkResponse(
     *            ))； 若不是登录请求，则在请求时将cookie值放入请求头中
     * @param listener
     *            请求成功监听器
     * @param errorListener
     *            请求失败监听器
     */
    public JsonListRequest(String url, Class<T> clazz, Type type,
                           Boolean isLogin, Listener<T> listener, ErrorListener errorListener) {
        this(url, null, clazz, type, isLogin, listener, errorListener);
    }

    /**
     * GET请求方式,将json中的key对应的value解析为 对应的clazz对象
     * 
     * @param url
     *            请求url
     * @param key
     *            取得指定的key,<b>NOTE:</b>只支持 root-key，所有子key均错误
     * @param clazz
     *            解析的class字节码：当key为null时，clazz也为null
     * @param type
     *            目标类型
     * @param isLogin
     *            是否是登录请求，若为登录请求，则在返回的响应的header中得到cookie(参见parseNetworkResponse(
     *            ))； 若不是登录请求，则在请求的header中加入cookie
     * @param listener
     *            请求成功监听器
     * @param errorListener
     *            请求失败监听器
     */
    public JsonListRequest(String url, String key, Class<T> clazz, Type type,
                           Boolean isLogin, Listener<T> listener, ErrorListener errorListener) {
        this(Method.GET, url, null, key, clazz, type, isLogin, listener,
                errorListener);
    }

    /**
     * 
     * @param method
     *            请求方法 Use {@link com.android.volley.Request.Method}.
     * @param url
     * @param requestBody
     * 
     * @param key
     *            取得指定的key,<b>NOTE:</b>只支持 root-key，所有子key均错误
     * @param clazz
     *            解析的class字节码:当key为null时，clazz也为null
     * @param type
     *            目标类型
     * @param isLogin
     *            是否是登录请求，若为登录请求，则在返回的响应的header中得到cookie(参见parseNetworkResponse(
     *            ))； 若不是登录请求，则在请求的header中加入cookie
     * @param listener
     *            请求成功监听器
     * @param errorListener
     *            请求失败监听器
     */
    public JsonListRequest(int method, String url, String requestBody,
                           String key, Class<T> clazz, Type type, Boolean isLogin,
                           Listener<T> listener, ErrorListener errorListener) {
        super(method, url, requestBody, listener, errorListener);
        Log.i(TAG, url);
        this.clazz = clazz;
        mKey = key;
        this.type = type;
        this.isLogin = isLogin;
        gson = new Gson();
    }

    /**
     * 
     * @param method
     *            请求方法 Use {@link com.android.volley.Request.Method}.
     * @param url
     * @param requestBody
     * 
     * @param clazz
     *            解析的class字节码:当key为null时，clazz也为null
     * @param type
     *            目标类型
     * @param isLogin
     *            是否是登录请求，若为登录请求，则在返回的响应的header中得到cookie(参见parseNetworkResponse(
     *            ))； 若不是登录请求，则在请求的header中加入cookie
     * @param listener
     *            请求成功监听器
     * @param errorListener
     *            请求失败监听器
     */
    public JsonListRequest(int method, String url, String requestBody,
                           Class<T> clazz, Type type, Boolean isLogin, Listener<T> listener,
                           ErrorListener errorListener) {
        super(method, url, requestBody, listener, errorListener);
        this.type = type;
        this.clazz = clazz;
        this.isLogin = isLogin;
        this.requestBody = requestBody;
        gson = new Gson();
    }

    // /*
    // * TESTING
    // */
    // public JsonListRequest(Context mContext,int method, String url, String
    // requestBody, Listener<T> listener,
    // ErrorListener errorListener) {
    // super(method, url, requestBody, listener, errorListener);
    // this.context = context;
    // this.type = type;
    // this.clazz = clazz;
    // this.isLogin = isLogin;
    // this.requestBody = requestBody;
    // gson = new Gson();
    // if (null != context) {
    // sharedPreferences = context.getSharedPreferences(Constants.LOGIN_SET,
    // Context.MODE_PRIVATE);
    // }
    // }

    /**
     * TESTING
     * 
     * @param mContext
     * @param post
     * @param uRL_POST2
     * @param string
     * @param listener
     * @param errorListener
     */
    public JsonListRequest(Context mContext, int method, String uRL_POST2,
                           String requestBody, Listener<T> listener,
                           ErrorListener errorListener) {
        // TODO Auto-generated constructor stub
        super(method, uRL_POST2, requestBody, (Listener<T>) listener,
                errorListener);
        this.context = context;
        this.type = type;
        this.clazz = clazz;
        this.isLogin = isLogin;
        this.requestBody = requestBody;
        Log.i(TAG, "192  <volleyJsonObjectRequest>-- requestBody = "
                + requestBody.toString());
        gson = new Gson();
        if (null != context) {
            sharedPreferences = context.getSharedPreferences(
                    Constants.LOGIN_SET, Context.MODE_PRIVATE);
        }
    }

    /**
     * 
     * @param method
     *            请求方法 Use {@link com.android.volley.Request.Method}.
     * @param context
     * @param url
     * @param requestBody
     * @param key
     *            取得指定的key,<b>NOTE:</b>只支持 root-key，所有子key均错误
     * @param clazz
     *            解析的class字节码:当key为null时，clazz也为null
     * @param type
     *            目标类型
     * @param isLogin
     *            是否是登录请求，若为登录请求，则在返回的响应的header中得到cookie(参见parseNetworkResponse(
     *            ))； 若不是登录请求，则在请求的header中加入cookie
     * @param listener
     *            请求成功监听器
     * @param errorListener
     *            请求失败监听器
     */
    public JsonListRequest(Context context, int method, String url,
                           String requestBody, String key, Class<T> clazz, Type type,
                           Boolean isLogin, Listener<T> listener, ErrorListener errorListener) {
        super(method, url/* + "?timestamp=" + new Random() */, requestBody,
                listener, errorListener);
        this.context = context;
        this.type = type;
        this.clazz = clazz;
        this.isLogin = isLogin;
        this.requestBody = requestBody;
        gson = new Gson();
        if (null != context) {
            sharedPreferences = context.getSharedPreferences(
                    Constants.LOGIN_SET, Context.MODE_PRIVATE);
        }
    }

    /**
     * only for 小微项目登录接口！！！登录成功与登录失败时响应的数据类型不同！！！
     * 
     * @param method
     *            请求方法 Use {@link com.android.volley.Request.Method}.
     * @param context
     * @param url
     * @param requestBody
     * @param key
     *            取得指定的key,<b>NOTE:</b>只支持 root-key，所有子key均错误
     * @param clazz
     *            解析的class字节码:当key为null时，clazz也为null
     * @param type
     *            目标类型： 登录失败时响应的数据类型
     * @param type2
     *            目标类型：登录成功时响应的数据类型
     * @param isLogin
     *            是否是登录请求，若为登录请求，则在返回的响应的header中得到cookie(参见parseNetworkResponse(
     *            ))； 若不是登录请求，则在请求的header中加入cookie
     * @param listener
     *            请求成功监听器
     * @param errorListener
     *            请求失败监听器
     */
    public JsonListRequest(Context context, int method, String url,
                           String requestBody, String key, Class<T> clazz, Type type,
                           Type type2, Boolean isLogin, Listener<T> listener,
                           ErrorListener errorListener) {
        super(method, url/* + "?timestamp=" + new Random() */, requestBody,
                listener, errorListener);
        this.context = context;
        this.type = type;
        this.type2 = type2;
        this.clazz = clazz;
        this.isLogin = isLogin;
        this.requestBody = requestBody;
        gson = new Gson();
        if (null != context) {
            sharedPreferences = context.getSharedPreferences(
                    Constants.LOGIN_SET, Context.MODE_PRIVATE);
        }
    }

    // @Override
    // public RetryPolicy getRetryPolicy() {
    // RetryPolicy retryPolicy = new
    // DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,
    // DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
    // DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
    // return retryPolicy;
    // }
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> params = new HashMap<String, String>();
        params.put("dataType", "json");
        params.put("x-form-id", "FAKEFORM");
        params.put("X-Requested-With", "XMLHttpRequest");
        params.put("Content-Type", "application/json; charset=UTF-8");
        // params.put("Cache-Control", "no-cache");
        params.put("data", requestBody);
        if (isLogin) {
            if (null != sharedPreferences) {
                cookie = sharedPreferences.getString(Constants.TOKEN, "");
                Log.i(TAG, "<getHeaders> -- lwx -- cookie = " + cookie);
            }
            if (!("").equals(cookie)) {
                params.put("Cookie", cookie);
            }
        }
        Log.i(TAG, "<getHeaders>" + params.toString());
        return params;
    }

    // @Override
    // protected Map<String, String> getParams() throws AuthFailureError {
    // Map<String, String> params = new HashMap<String, String>();
    // params.put("data", requestBody);
    // Log.i("getParams", params.toString());
    // return params;
    // }

    // @Override
    // public String getBodyContentType() {
    // return "application/x-www-form-urlencoded; charset=" +
    // getParamsEncoding();
    // }
    //解析网络请求  T 根据给的类解析数据
    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        // 解析网络响应
        try {
            String json = new String(response.data, "utf-8");
            T t = null;
            JsonObject jsonObject = gson.fromJson(json, JsonObject.class);
            t = gson.fromJson(json, type);
            Log.i(TAG,
                    "<parseNetworkResponse> 333 -- json = "
                            + Response.success(t, HttpHeaderParser
                                    .parseCacheHeaders(response)));
            return Response.success(t,
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            return Response.error(new ParseError(e));
        }
    }
}

// @Override
// protected Response<T> parseNetworkResponse(NetworkResponse response) {
// // 解析网络响应
// try {
// String json = new String(response.data, "utf-8");
// Log.i(TAG, "<parseNetworkResponse> -- json = " + json);
// if (isLogin) {
// // 若为登录的网络响应，则取出header中的cookie
// String STCookieJess = null; // start with "JSESSIONID="
// String STCookieST = null; // start with "ST="
// if (null != response.apacheHeaders) {
// for (int i = 0; i < response.apacheHeaders.length; i++) {
// String key = response.apacheHeaders[i].getName();
// String value = response.apacheHeaders[i].getValue();
// Log.d(TAG, "<parseNetworkResponse> -- key = " + key + "; value = " + value);
// if (key.equalsIgnoreCase("Set-cookie") && value.startsWith("JSESSIONID=")) {
// STCookieJess = value;
// String[] cookieArr = STCookieJess.split(";", -1);
// if (cookieArr.length > 0) {
// STCookieJess = cookieArr[0];
// }
// Log.d(TAG, "<parseNetworkResponse> -- 11 -- STCookieJess = " + STCookieJess);
// }
// if (key.equalsIgnoreCase("Set-cookie") && value.startsWith("ST=")) {
// STCookieST = value;
// String[] cookieArr = STCookieST.split(";", -1);
// if (cookieArr.length > 0) {
// STCookieST = cookieArr[0];
// }
// Log.d(TAG, "<parseNetworkResponse> -- 22 -- STCookieST = " + STCookieST);
// }
// }
// cookie = STCookieJess + "; " + STCookieST;
// }
// if (null != cookie) {
// if (null != sharedPreferences) {
// sharedPreferences.edit().putString(Constant.COOKIE, cookie).commit();
// }
// }
// }
// T t = null;
// if (isLogin) {
// // only for 小微项目的登录接口： 因为登录成功与登录失败时响应的类型不同
// JsonObject jsonObject = gson.fromJson(json, JsonObject.class);
// if (Constant.SUCCESS == jsonObject.get("code").getAsInt()) {
// // 小微项目的登录接口： 登录成功时的Json解析
// t = JsonUtil.json2Any(json, type2);
// } else {
// // 小微项目的登录接口： 登录失败时的Json解析
// t = JsonUtil.json2Any(json, type);
// }
// } else {
// JsonObject jsonObject = gson.fromJson(json, JsonObject.class);
// if (mKey == null) {
// // t = gson.fromJson(json, clazz);
// t = JsonUtil.json2Any(json, type);
// } else if
// ((Constant.VALIDATION_ERROR).equals(jsonObject.get("code").getAsString())) {
// t = JsonUtil.json2Any(json, type2);
// } else {
// t = gson.fromJson(jsonObject.get(mKey), clazz);
// }
// }
// return Response.success(t, HttpHeaderParser.parseCacheHeaders(response));
// } catch (UnsupportedEncodingException e) {
// return Response.error(new ParseError(e));
// } catch (JsonSyntaxException e) {
// return Response.error(new ParseError(e));
// }
// }
// }
